package net.yla.smartbus.module.ba.right.admin.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.vip.vjtools.vjkit.collection.ListUtil;
import net.yla.smartbus.core.api.RequestCode;
import net.yla.smartbus.core.base.BaseService;
import net.yla.smartbus.core.base.PageBean;
import net.yla.smartbus.core.exception.AppException;
import net.yla.smartbus.core.util.*;
import net.yla.smartbus.core.util.mini.ChineseUtils;
import net.yla.smartbus.core.util.qqwry.ext.QQWry;
import net.yla.smartbus.module.ba.right.admin.dto.AdminDTO;
import net.yla.smartbus.module.ba.right.admin.entity.AdminDO;
import net.yla.smartbus.module.ba.right.admin.entity.AdminLoginLogsDO;
import net.yla.smartbus.module.ba.right.admin.mapper.AdminLoginLogsMapper;
import net.yla.smartbus.module.ba.right.admin.mapper.AdminMapper;
import net.yla.smartbus.module.ba.right.admin.query.*;
import net.yla.smartbus.module.ba.right.admin.service.AdminLoginLogsService;
import net.yla.smartbus.module.ba.right.admin.service.AdminLoginTracesService;
import net.yla.smartbus.module.ba.right.admin.service.AdminService;
import net.yla.smartbus.module.ba.right.roleRL.entity.AdminRoleRL;
import net.yla.smartbus.module.ba.right.roleRL.mapper.RoleRLMapper;
import net.yla.smartbus.module.ba.right.roles.mapper.RolesMapper;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Date: 2020-08-17 9:58
 * @Author: Being Nobody
 * @Version: 1.0
 */
@Service
public class AdminServiceImpl extends BaseService implements AdminService {

    @Resource
    private AdminMapper adminMapper;
    @Resource
    private AdminLoginTracesService tracesService;
    @Resource
    private AdminLoginLogsService loginLogsService;
    @Resource
    private RolesMapper rolesMapper;
    @Autowired
    QQWry qqWry;
    @Autowired
    private RoleRLMapper roleRLMapper;
    @Autowired
    private AdminLoginLogsMapper adminLoginLogsMapper;
    @Value("${erp.switch}")
    private String eSwitch;

    @Override
    public int deleteByPrimaryKey(Integer adminId) {
        return adminMapper.deleteByPrimaryKey(adminId);
    }

    @Override
    public int insert(AdminDO record) {
        return adminMapper.insert(record);
    }

    @Override
    public int insertSelective(AdminDO record) {
        return adminMapper.insertSelective(record);
    }

    @Override
    public AdminDO selectByPrimaryKey(Integer adminId) {
        return adminMapper.selectByPrimaryKey(adminId);
    }

    @Override
    public int updateByPrimaryKeySelective(AdminDO record) {
        return adminMapper.updateByPrimaryKeySelective(record);
    }


    /**
     * 逻辑删除
     *
     * @param record
     * @return
     */
    @Override
    public int updateByPrimaryKey(AdminDO record) {
        // 校验
        Integer adminid = record.getAdminId();
        if (adminid != null) {
            // 隐藏
            record.setHidden(1);
            return adminMapper.updateByPrimaryKeySelective(record);
        }
        if(eSwitch.equals(1)) {
            HttpClientUtil.sendDataErp("{\"table\":\"user\",\"id\":" + record.getAdminId() + ",\"action\":2}");
        }
        return 1;
    }

    /**
     * 分页查询
     * TODO 页码有问题！
     *
     * @param query
     * @return
     */
    @Override
    public PageBean<JSONObject> admin(AdminQuery query) {
        // 分页 查询的字段
//        List<String> fields = super.selected(AdminDO.class, query.getFields());
//        query.setFields(fields);
        String sortOrder = super.orderBy(query.getSort(), query.getOrder());
        PageHelper.startPage(query.getPage(), query.getSize(), sortOrder.isEmpty() ? "adminId" : sortOrder);
        List<AdminDO> list = adminMapper.admin(query);
        PageInfo pageInfo = new PageInfo(list);
        int total = (int) pageInfo.getTotal();
        List<JSONObject> list1 = this.pageOfAdmin(list, query.getFields());
        return new PageBean<>(list1, query.getPage(), query.getSize(), total);
    }

    @Override
    public int saveSelective(SaveQuery query) {
        // 校验参数
//        this.checkParam(query);
        int save = this.save(query);
        return save;
    }

    private int save(SaveQuery query) {
        // 添加
        return query.getId() == null ? this.add(query) : this.update(query);
    }

    /**
     * 更新管理员信息
     *
     * @param query
     * @return
     */
    private int update(SaveQuery query) {
        // loginId不能重复
        AdminDO admin1 = adminMapper.checkLoginId(query.getId(), query.getLoginId());
        if (admin1 != null) {
            throw new AppException("用户名已经存在", RequestCode.Form_Validate_Error);
        }
        if (query.getLoginPwd()==null){
            throw new AppException("密码有误", RequestCode.Form_Validate_Error);
        }
        // 修改默认值
        super.updateSetDefaultValue(query);
        AdminDO admin = new AdminDO();
//        BeanUtils.copyProperties(query, admin);
        admin.setAdminId(query.getId());
        admin.setLoginId(query.getLoginId());
        admin.setState(query.getState());
        LocalDateTime now = LocalDateTime.now();
        if (query.getState() == 3) {
            admin.setLockedTime(now);
            admin.setLastLoginTime(now);
        }
        admin.setDisabled(query.getDisabled());
        admin.setNickName(query.getNickName() != null && query.getNickName() != "" ? query.getNickName() : query.getLoginId());
        if (query.getLoginPwd() != null) {
            //修改密码
            admin.setLoginPwd(md5Password(query.getLoginId(), query.getLoginPwd()));
        }
        if (eSwitch.equals(1)) {
            HttpClientUtil.sendDataErp("{\"table\":\"user\",\"id\":" + admin.getAdminId() + ",\"action\":1}");
        }
        // 正常更新
        return adminMapper.updateByPrimaryKeySelective(admin);
    }

    /**
     * 添加
     *
     * @param query
     * @return
     */
    private int add(SaveQuery query) {
        AdminDO adminDO = adminMapper.selectByLoginId(query.getLoginId());
        if (adminDO != null) {
            throw new AppException("用户名已经存在", RequestCode.Form_Validate_Error);
        }
        // 修改IP？
        // 修改别名 数据库别名不允许为空
        query.setNickName(ChineseUtils.getPinYinHeadChar(query.getLoginId()));
        AdminDO admin = new AdminDO();
        admin.setLoginId(query.getLoginId());
        admin.setNickName(query.getNickName() != null && query.getNickName() != "" ? query.getNickName() : query.getLoginId());
//        BeanUtils.copyProperties(query, admin);
        admin.setState(query.getState());
        admin.setDisabled(query.getDisabled());
        if (query.getLoginPwd() != null) {
            //修改密码
            admin.setLoginPwd(md5Password(query.getLoginId(), query.getLoginPwd()));
        }
        int i = adminMapper.insertSelective(admin);
        if(eSwitch.equals(1)) {
            HttpClientUtil.sendDataErp("{\"table\":\"user\",\"id\":" + admin.getAdminId() + ",\"action\":0}");
        }
        return i;
    }

    /**
     * md5加密
     *
     * @param loginId
     * @param loginPwd
     * @return
     */
    private String md5Password(String loginId, String loginPwd) {
        return ShiroUtils.md5(loginId, loginPwd);
    }

    /**
     * 通过loginId获取管理员记录
     * hidden=0
     *
     * @param loginid
     * @return
     */
    public AdminDO selectByLoginId(String loginid) {
        return adminMapper.selectByLoginId(loginid);
    }

    /**
     * 参数校验
     *
     * @param query
     */
    private void checkParam(SaveQuery query) {
        // 账户名
        if (StringUtils.isEmpty(query.getLoginId())) {
            throw new AppException("用户名为空", RequestCode.Form_Validate_Error);
        }
        // 密码
        if (StringUtils.isEmpty(query.getLoginPwd())) {
            throw new AppException("密码为空", RequestCode.Form_Validate_Error);
        }
    }


    /**
     * 查询符合条件的记录数
     *
     * @param query
     * @return
     */
    @Override
    public int count(AdminCount query) {
        return adminMapper.countByQuery(query);
    }

    /**
     * 查询符合条件的记录
     *
     * @param query
     * @return
     */
    @Override
    public AdminDTO record(AdminQuery query) {

        return null;
    }

    /**
     * IP跟踪记录信息数量 多点登录
     *
     * @param count
     * @return
     */
    @Override
    public int ipOfCount(IPCount count) {
        return tracesService.ipOfCount(count);
    }

    /**
     * 查询IP跟踪信息的记录集
     *
     * @param query
     * @return
     */
    @Override
    public List<JSONObject> ipOfQuery(IPQuery query) {
        // 分页
        String sortOrder = super.orderBy(query.getSort(), query.getOrder());
//        PageHelper.offsetPage(query.getOffset(), query.getCount(), sortOrder.isEmpty() ? "traceId" : sortOrder);
        List<JSONObject> list = tracesService.ipOfQuery(query);
        return list;
    }

    /**
     * 获取管理员登录日志的记录数
     *
     * @param query
     * @return
     */
    @Override
    public int logOfCount(LogCount query) {
        long ip = IPUtil.ipv4ToLong(query.getIp());
        return loginLogsService.logOfCount(query, ip);
    }

    /**
     * 查询管理员登录日志的记录集
     *
     * @param query
     * @return
     */
    @Override
    public PageBean<JSONObject> logOfQuery(LogQuery query) {
        Long ip = null;
        if (StringUtils.isNotEmpty(query.getIp())) {
            ip = IPUtil.ipv4ToLong(query.getIp());
        }
        return loginLogsService.logOfQuery(query, ip);
    }

    /**
     * 查看管理员记录信息
     *
     * @param id
     * @return
     */
    @Override
    public AdminDTO admin(Integer id) {
        AdminDO admin1 = adminMapper.selectByPrimaryKey(id);
        AdminDTO dto = null;
        if (admin1 != null) {
            dto = new AdminDTO();
            BeanUtils.copyProperties(admin1, dto);
            dto.setId(admin1.getAdminId());
            dto.setErrorCount(admin1.getErrorCount1());
            dto.setStamp(admin1.getStamp1());
        }
        return dto;
    }

    /**
     * 逻辑删除
     *
     * @param id
     * @return
     */
    @Override
    public int delAdmin(Integer id) {
        if (id == null) {
            throw new AppException("标识号不能为空", RequestCode.Operate_Tip);
        }
        if (eSwitch.equals(1)){
            HttpClientUtil.sendDataErp("{\"table\":\"user\",\"id\":" + id + ",\"action\":2}");
        }
        return adminMapper.delAdmin(id);
    }

    /**
     * 批量删除
     *
     * @param adminIds
     * @return
     */
    @Override
    public int deleteByList(List<Integer> adminIds) {
        for (Integer id : adminIds) {
            if (this.delAdmin(id) < 0) {
                throw new AppException("删除账号失败", RequestCode.Form_Validate_Error);
            }
        }
        return 1;
    }

    /**
     * 根据traceId获取对象信息
     *
     * @param traceId
     * @return
     */
    @Override
    public JSONObject ipOfView(Integer traceId) {
        return tracesService.ipOfView(traceId);
    }

    /**
     * 查看管理员登录日志记录
     *
     * @param logId
     * @return
     */
    @Override
    public JSONObject logOfView(Integer logId) {
        return loginLogsService.logOfView(logId);
    }

    /**
     * 导出
     *
     * @param query
     * @return
     */
    @Override
    public void export(AdminQuery query, HttpServletResponse response) {
        ExcelData data = new ExcelData();
        List<AdminDO> adminDOList = adminMapper.admin(query);
        data.setName("账号信息");
        List<String> titles = new LinkedList<>();
        titles.add("账号名称");
        titles.add("状态");
        titles.add("最后登录");
        titles.add("客户端");
        titles.add("账号锁定时间");
        titles.add("账号创建时间");
        data.setTitles(titles);
        List<List<Object>> rows = new LinkedList<>();
        List<Object> row = null;
        if (adminDOList != null) {
            for (AdminDO adminDO : adminDOList) {
                row = new LinkedList<>();
                row.add(adminDO.getLoginId());
                row.add(adminDO.getState());
                row.add(adminDO.getLastLoginIP());
                /*row.add(adminDO.getLastLoginTime());*/
                row.add(adminDO.getHidden());
                row.add(adminDO.getLockedTime());
                row.add(adminDO.getCreationTime());
                rows.add(row);
            }
        }
        data.setRows(rows);
        ExcelUtils.exportExcel(response, "设备信息导出.xls", data);
    }

    //删除账号日志信息
    @Override
    public int deleteAdminLog(Integer logId) {
        return adminLoginLogsMapper.deleteByPrimaryKey(logId);
    }

    //批量删除账号日志信息
    @Override
    public int deleteByLogList(List<Integer> ids) {
        for (Integer id : ids) {
            if (this.deleteAdminLog(id) < 0) {
                throw new AppException("删除账号失败", RequestCode.Form_Validate_Error);
            }
        }
        return 1;
    }

    /**
     * 查询未绑定其他角色的全部账号
     *
     * @param id
     * @return
     */
    @Override
    public List<JSONObject> getAdminNoRoleInfo(Integer id) {
        List<AdminDO> admins = adminMapper.admin(new AdminQuery());
        List<JSONObject> jsonObjects = new LinkedList<>();
        for (AdminDO admin : admins) {
            JSONObject jsonObject = new JSONObject();
            AdminRoleRL adminRoleRL = roleRLMapper.selectByAdminId(admin.getAdminId());
            if (adminRoleRL != null && adminRoleRL.getRoleId() != id) {
                jsonObject.put("disabled", true);
            } else {
                jsonObject.put("disabled", false);
            }
            jsonObject.put("id", admin.getAdminId());
            jsonObject.put("loginId", adminMapper.selectByPrimaryKey(admin.getAdminId()).getLoginId());
            jsonObjects.add(jsonObject);
        }
        return jsonObjects;
    }

    /**
     * 封装
     *
     * @param list
     * @return
     */
    private List<JSONObject> pageOfAdmin(List<AdminDO> list, List<String> fields) {
        List<JSONObject> result = null;
        if (ListUtil.isNotEmpty(list)) {
            result = new ArrayList<>(list.size());
            for (AdminDO admin1 : list) {
                JSONObject object = PojoJsonUtil.writeJsonByField(admin1, fields);
                // TODO 当前用户含有的角色
                //获取登录时间
                object.put("lastLoginTime", admin1.getLastLoginTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

                /*object.put("lockedTime", admin1.getLockedTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))+"-已锁定");*/
                //类型转换java.time.LocalDateTime --> java.util.Date
                LocalDateTime localDateTime = admin1.getLockedTime();
                ZoneId zone = ZoneId.systemDefault();
                Instant instant = localDateTime.atZone(zone).toInstant();
                java.util.Date date = Date.from(instant);

                //判断账号最后锁定时间
                if (admin1.getLockedTime() != null) {
                    String format = admin1.getLockedTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    if (!format.equals("1900-01-01 00:00:00")) {
                        object.put("lockedTime", format);
                    } else {
                        object.put("lockedTime", "--");
                    }
                }
                //账号创建时间
                object.put("creationTime", admin1.getCreationTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                //账号最后登录IP
                if (admin1.getLastLoginIP() != null && admin1.getLastLoginIP() != 0) {
                    object.put("lastLoginIP", qqWry.findIP(IPUtil.longToIpv4(admin1.getLastLoginIP())).getMainInfo());
                    object.put("lastLoginIP2", IPUtil.longToIpv4(admin1.getLastLoginIP()));
                } else {
                    object.put("lastLoginIP", "");
                    object.put("lastLoginIP2", "保留地址");
                }
                //获取headers
                AdminLoginLogsDO adminLoginLogs = adminLoginLogsMapper.selectByLogId(admin1.getAdminId());
                if (adminLoginLogs != null) {
                    UserAgent userAgent = UserAgent.parseUserAgentString(adminLoginLogs.getHeaders());
                    object.put("browser", userAgent.getBrowser().toString().substring(0, 1).toUpperCase() + userAgent.getBrowser().toString().substring(1).toLowerCase());
                    object.put("system", userAgent.getOperatingSystem().toString().substring(0, 1).toUpperCase() + userAgent.getOperatingSystem().toString().substring(1).toLowerCase());
                } else {
                    object.put("browser", "- - -");
                    object.put("system", "- - -");
                }
                result.add(object);
            }
        }
        return result;
    }
}

